#include <QtOpenGL/QGLWidget>
#include <cmath>
#include <QtConcurrentMap>
#include <QDebug>


#include "losttankwindow.h"
#include "ui_losttankwindow.h"

bool LostTankWindow::pressedForward=false;
bool LostTankWindow::pressedBack=false;
bool LostTankWindow::pressedRotateLeft=false;
bool LostTankWindow::pressedRotateRight=false;
bool LostTankWindow::pressedBrake=false;
bool LostTankWindow::pressedFire=false;
bool LostTankWindow::pressedAutoObjective=false;
bool LostTankWindow::pressedAutoPackage=false;
bool LostTankWindow::pressedLead=false;
bool LostTankWindow::pressedGrid=false;

float LostTankWindow::speedCoefficient=10.5;


LostTankWindow::LostTankWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::LostTankWindow)
{
    ui->setupUi(this);
    ui->topView->setScene(&topScene);
    ui->centralView->setScene(&arena);
    ui->bottomView->setScene(&bottomScene);

    actions.insert(Qt::Key_W,FORWARD);
    actions.insert(Qt::Key_S,BACK);
    actions.insert(Qt::Key_A,ROTATE_LEFT);
    actions.insert(Qt::Key_D,ROTATE_RIGHT);
    actions.insert(Qt::Key_Space,BRAKE);
    actions.insert(Qt::Key_Shift,FIRE);
    actions.insert(Qt::Key_O,AUTO_OBJECTIVE);
    actions.insert(Qt::Key_P,AUTO_PACKAGE);
    actions.insert(Qt::Key_L,LEAD);
    actions.insert(Qt::Key_1,GRID);
    actions.insert(Qt::Key_Escape,EXIT);

    setCursor(QCursor(Qt::BlankCursor ));

    ui->centralView->setRenderHint(QPainter::Antialiasing);
    ui->centralView->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
    ui->centralView->setCacheMode(QGraphicsView::CacheBackground);
    ui->centralView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->centralView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->centralView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    ui->centralView->setStyleSheet("QGraphicsView {border-style:none;}");

    arena.setBackground(QPixmap(":/resources/texture.png"));
    Purgatory* purgatory=new Purgatory;
    arena.addPurgatory(purgatory);
    arena.buildGrid();
    arena.buildLevel(1);
    arena.addPlayer(new Player,3,3);

    angle.setPos(-500,0);
    bottomScene.addItem(&angle);

    speed.setPos(-300,0);
    bottomScene.addItem(&speed);

    shield.setPos(-100,0);
    bottomScene.addItem(&shield);

    health.setPos(100,0);
    bottomScene.addItem(&health);

    xcord.setPos(300,0);
    bottomScene.addItem(&xcord);

    ycord.setPos(500,0);
    bottomScene.addItem(&ycord);

    packages.setPos(400,0);
    topScene.addItem(&packages);

    objectives.setPos(-400,0);
    topScene.addItem(&objectives);

    this->showFullScreen();
    this->setFocus();

    timer.start(30);
    connect(&timer, SIGNAL(timeout()), this, SLOT(mainClock()));
}

LostTankWindow::~LostTankWindow()
{
    delete ui;
}


void LostTankWindow::keyPressEvent( QKeyEvent *event )
{
    if (event->isAutoRepeat() || !actions.contains( event->key() ) )
    {
        event->ignore();
        return;
    }


    Action action = actions[event->key()];
    switch ( action )
    {
    case FORWARD:
        pressedForward=true;
        pressedAutoObjective=false;
        pressedAutoPackage=false;
        pressedLead=false;
        break;
    case BACK:
        pressedBack=true;
        pressedAutoObjective=false;
        pressedAutoPackage=false;
        pressedLead=false;
        break;
    case ROTATE_LEFT:
        pressedRotateLeft=true;
        pressedAutoObjective=false;
        pressedAutoPackage=false;
        pressedLead=false;
        break;
    case ROTATE_RIGHT:
        pressedRotateRight=true;
        pressedAutoObjective=false;
        pressedAutoPackage=false;
        pressedLead=false;
        break;
    case FIRE:
        pressedFire=true;
        break;
    case BRAKE:
        pressedBrake=true;
        pressedAutoObjective=false;
        pressedAutoPackage=false;
        pressedLead=false;
        break;
    case AUTO_OBJECTIVE:
        pressedAutoObjective=true;
        pressedAutoPackage=false;
        pressedLead=false;
        break;
    case AUTO_PACKAGE:
        pressedAutoObjective=false;
        pressedAutoPackage=true;
        pressedLead=false;
        break;
    case LEAD:
        pressedAutoObjective=false;
        pressedAutoPackage=false;
        pressedLead=true;
        break;
    case EXIT:
        close();
        break;
    default:
        event->ignore();
        return;
    }
    event->accept();
}

void LostTankWindow::keyReleaseEvent(QKeyEvent *event)
{
    if ( event->isAutoRepeat() || !actions.contains( event->key() ) )
    {
        event->ignore();
        return;
    }

    Action action = actions[event->key()];
    switch ( action )
    {
    case FORWARD:
        pressedForward=false;
        break;
    case BACK:
        pressedBack=false;
        break;
    case ROTATE_LEFT:
        pressedRotateLeft=false;
        break;
    case ROTATE_RIGHT:
        pressedRotateRight=false;
        break;
    case FIRE:
        pressedFire=false;
        break;
    case BRAKE:
        pressedBrake=false;
        break;
    case AUTO_OBJECTIVE:
        break;
    case AUTO_PACKAGE:
        break;
    case LEAD:
        break;
    case GRID:
        pressedGrid=true;
        break;
    default:
        event->ignore();
        return;
    }
    event->accept();
}




void LostTankWindow::mainClock()
{
    Player* player=arena.grid->player;
    processArena();
    processPlayer(player);


    if(player->alive) processObjectives();
    processBullets();

    ui->centralView->centerOn(player);
    arena.update();
}

void LostTankWindow::processArena()
{
    if(pressedGrid)
    {

        for(auto r:arena.rects)
            r->setVisible(!r->isVisible());
        pressedGrid=false;
    }

}

void LostTankWindow::processObjectives()
{
    for(auto x:arena.grid->objects[ot::OBJECTIVE])
    {
        auto o=static_cast<Objective*>(x);
        if(!o->alive)continue;
        o->control();
        o->physics();
        o->step();

    }
}

void LostTankWindow::processBullets()
{
    for(auto x:arena.grid->objects[ot::BULLET])
    {
        auto o=static_cast<Bullet*>(x);
        if(!o->alive)continue;
        o->control();
        o->physics();
        o->step();

    }

}



void LostTankWindow::processPlayer(Player *p)
{

    if(p->alive)
    {
        p->control();
        p->physics();
        p->step();
    }

    speed.setPlainText("Speed: "+QString::number(abs(p->speed*speedCoefficient),'i',0)+" km/h");
    angle.setPlainText("Angle: "+QString::number(p->angle,'i',0));
    xcord.setPlainText("x = "+QString::number(p->tile->x,'i',0));
    ycord.setPlainText("y = "+QString::number(p->tile->y,'i',0));
    shield.setPlainText("Shield: "+QString::number(p->shield,'i',0));
    health.setPlainText("Health: "+QString::number(p->health,'i',0));

    QString s,s2;


    if(!p->grid->objects[ot::PACKAGE].empty())
    {
        auto v=p->grid->objects[ot::PACKAGE][0]->tile;
        s="Package     x= "+QString::number(v->x,'i',0)+" y= "+
                QString::number(v->y,'i',0);
    }
    if(!p->grid->objects[ot::OBJECTIVE].empty())
    {
        auto v=p->grid->objects[ot::OBJECTIVE][0]->tile;
        s2="Objective     x= "+QString::number(v->x,'i',0)+" y= "+
                QString::number(v->y,'i',0);
    }
    packages.setPlainText(s);
    objectives.setPlainText(s2);
}
